package com.iwhalecloud.bss.kite.cucc.order.accept.constructor.inst;

import com.google.common.collect.Sets;
import com.iwhalecloud.bss.kite.common.constant.KeyConsts;
import com.iwhalecloud.bss.kite.common.constant.TableConsts;
import com.iwhalecloud.bss.kite.common.util.KiteBeanUtils;
import com.iwhalecloud.bss.kite.common.util.KiteStringUtils;
import com.iwhalecloud.bss.kite.cucc.order.util.AcceptUtils;
import com.iwhalecloud.bss.kite.dataservice.cache.OfferCache;
import com.iwhalecloud.bss.kite.dataservice.entity.inst.OfferInst;
import com.iwhalecloud.bss.kite.dataservice.entity.inst.OfferInstAttr;
import com.iwhalecloud.bss.kite.dataservice.entity.spec.Offer;
import com.iwhalecloud.bss.kite.dataservice.mapper.inst.OfferInstAttrMapper;
import com.iwhalecloud.bss.kite.dataservice.util.IdUtils;
import com.iwhalecloud.bss.kite.manager.api.IQuerySceneInstService;
import com.iwhalecloud.bss.kite.manager.enums.ActionType;
import com.iwhalecloud.bss.kite.manager.enums.InstType;
import com.iwhalecloud.bss.kite.manager.inst.KiteAttr;
import com.iwhalecloud.bss.kite.manager.inst.KiteInst;
import com.iwhalecloud.bss.kite.manager.inst.KiteOfferInst;
import com.iwhalecloud.bss.kite.manager.inst.change.KiteInstChange;
import com.iwhalecloud.bss.kite.manager.util.ManagerUtils;
import com.iwhalecloud.bss.kite.order.client.dto.InstContainer;
import com.iwhalecloud.bss.kite.order.client.dto.OrderRequest;
import com.ztesoft.bss.base.staticdata.CoreDataOffer;
import com.ztesoft.bss.base.staticdata.CoreDataProdInst;
import com.ztesoft.bss.common.util.SpringUtil;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import tk.mybatis.mapper.entity.Example;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;

/**
 * 销售品实例构造器
 */
@Component
public class OfferInstConstructor extends InstConstructor<KiteOfferInst, OfferInst> {

    @Override
    public String getTableName() {
        return TableConsts.OfferInst.getTableName();
    }

    @Override
    public OfferInst build(OrderRequest orderRequest, String offerInstId, Map<String, Object> params) {
        if (Objects.isNull(orderRequest) || StringUtils.isBlank(offerInstId)) {
            return null;
        }

        IQuerySceneInstService querySceneInstService = SpringUtil.getBean(IQuerySceneInstService.class);
        KiteOfferInst kiteOfferInst = querySceneInstService.getOfferInst(orderRequest.getCustId(), offerInstId);
        OfferInst offerInst = convert(orderRequest, kiteOfferInst, params);
        if (Objects.nonNull(offerInst)) {
            Offer offer = OfferCache.get(offerInst.getOfferId());
            String offerType = Optional.ofNullable(offer).map(Offer::getOfferType).orElse("");
            if (StringUtils.isNotBlank(offerType) && !KiteStringUtils.equals(offerType, offerInst.getOfferType())) {
                // 如果实例的offerType跟规格数据的不一样，则改回正确的
                offerInst.setOfferType(offerType);
            }
        }
        InstContainer.ofRequest(orderRequest).addOfferInst(offerInst);

        Map<String, OfferInstAttr> offerInstAttrMap = buildOfferInstAttrs(orderRequest, kiteOfferInst,
            offerInst.getOwnerCustId());
        orderRequest.getInstContainer().getOfferInstAttrMap().put(offerInstId, offerInstAttrMap);

        return offerInst;
    }

    @Override
    public OfferInst newInst(OrderRequest orderRequest, KiteOfferInst kiteOfferInst) {
        if (!ObjectUtils.allNotNull(orderRequest, kiteOfferInst)) {
            return null;
        }

        String compInstId = kiteOfferInst.getOfferInstId();
        if (Objects.equals(InstType.ADDITIONAL_OFFER_INST, kiteOfferInst.getInstType())) {
            IQuerySceneInstService querySceneInstService = SpringUtil.getBean(IQuerySceneInstService.class);
            compInstId = querySceneInstService.getAdditionalOfferInstCompInstId(orderRequest.getCustId(),
                kiteOfferInst.getOfferInstId());
        }

        Date now = new Date();
        Offer offer = OfferCache.get(kiteOfferInst.getOfferId());
        String regionId = orderRequest.getRegionId();
        regionId = StringUtils.isNotBlank(regionId) ? regionId : "-1";

        OfferInst offerInst = KiteBeanUtils.transform(kiteOfferInst, OfferInst.class, KiteInst.ACTION_TYPE);
        offerInst.setOwnerCustId(orderRequest.getCustId());
        offerInst.setActionType(ActionType.A.name());
        offerInst.setProdInstId(offerInst.getOfferInstId());
        offerInst.setProdTypeCd(KeyConsts.PROD_TYPE_CD_01);
        if (StringUtils.isBlank(offerInst.getUseCustId())) {
            offerInst.setUseCustId(orderRequest.getCustId());
        }
        offerInst.setCreateDate(now);
        offerInst.setStateCd(KeyConsts.STATE_ONWAY);
//        offerInst.setEffDate(effDate);
//        offerInst.setExpDate(expDate);
        offerInst.setLanId(orderRequest.getLanId());
        offerInst.setCompInstId(compInstId);
        offerInst.setCreateStaff(orderRequest.getStaffId());
//        offerInst.setEffDateType(effDateType);
//        offerInst.setExpDateType(expDateType);
        offerInst.setSpareFld0(kiteOfferInst.getOfferInstId());
        offerInst.setSeq("0");
        offerInst.setCustId(orderRequest.getCustId());
        offerInst.setStatusDate(now);
        offerInst.setCreateOrgId(orderRequest.getOrgId());
        offerInst.setUpdateStaff(orderRequest.getStaffId());
        offerInst.setUpdateDate(now);
        offerInst.setBusiModDate(now);
        offerInst.setLastOrderItemId("-1");
//        offerInst.setExpProcMethod(expProcMethod);
        offerInst.setOfferKind(Optional.ofNullable(offer).map(Offer::getOfferType).orElse(null));
        offerInst.setRegionId(regionId);
        offerInst.setOfferType(Optional.ofNullable(offer).map(Offer::getOfferType).orElse(null));
        offerInst.setStatusCd(CoreDataOffer.OFF_0003_1200);

        setAttrs(offerInst, kiteOfferInst.getAttrMap(),
            Sets.newHashSet(StringUtils.upperCase(TableConsts.OfferInst.getTableName())));

        return offerInst;
    }

    /**
     * 构造销售品实例属性
     * @param orderRequest
     * @param kiteOfferInst
     * @param custId
     * @return
     */
    public Map<String, OfferInstAttr> buildOfferInstAttrs(OrderRequest orderRequest, KiteOfferInst kiteOfferInst,
        String custId) {
        if (!ObjectUtils.allNotNull(orderRequest, kiteOfferInst)) {
            return new HashMap<>();
        }

        Map<String, OfferInstAttr> offerInstAttrMap = null;
        if (isAddByCurrent(orderRequest, kiteOfferInst)) {
            offerInstAttrMap = new HashMap<>();
            Set<Entry<String, KiteAttr>> entrySet = kiteOfferInst.getAttrMap().entrySet();
            for (Entry<String, KiteAttr> entry : entrySet) {
                KiteAttr attr = entry.getValue();
                if (!StringUtils.equalsIgnoreCase(TableConsts.OfferInstAttr.getTableName(), attr.getTableName())) {
                    continue;
                }

                OfferInstAttr offerInstAttr = toOfferInstAttr(orderRequest, attr, kiteOfferInst, custId);
                if (Objects.nonNull(offerInstAttr)) {
                    offerInstAttrMap.put(offerInstAttr.getFieldName(), offerInstAttr);
                }
            }
        }
        else {
            offerInstAttrMap = getOfferInstAttrMap(kiteOfferInst.getOfferInstId(), kiteOfferInst.getOwnerCustId());
            if (Objects.equals(ActionType.D, kiteOfferInst.getActionType())) {
                offerInstAttrMap.forEach((fieldName, offerInstAttr) -> {
                    AcceptUtils.setActionType(offerInstAttr, ActionType.D.name());
                });
            }
            else {
                Date now = new Date();
                Map<String, KiteAttr> attrMap = kiteOfferInst.getAttrMap();
                String key = ManagerUtils.join(kiteOfferInst.getInstType(), kiteOfferInst.getInstId());
                List<KiteInstChange> instChanges = orderRequest.getInstChangeMap().getOrDefault(key, new ArrayList<>());
                for (KiteInstChange instChange : instChanges) {
                    if (!Objects.equals(ActionType.M, instChange.getActionType())) {
                        continue;
                    }

                    String fieldName = instChange.getFieldName();
                    String newValue = instChange.getNewValue();

                    KiteAttr attr = attrMap.get(fieldName);
                    if (Objects.isNull(attr) || !StringUtils.equalsIgnoreCase(TableConsts.OfferInstAttr.getTableName(),
                        attr.getTableName())) {
                        continue;
                    }

                    OfferInstAttr offerInstAttr = offerInstAttrMap.get(fieldName);
                    if (Objects.nonNull(offerInstAttr)) {
                        // 修改属性
                        if (!KiteStringUtils.equals(newValue, offerInstAttr.getAttrValue())) {
                            offerInstAttr.setAttrValue(newValue);
                            offerInstAttr.setUpdateStaff(orderRequest.getStaffId());
                            offerInstAttr.setUpdateDate(now);
                            AcceptUtils.setActionType(offerInstAttr, ActionType.M.name());
                        }
                    }
                    else {
                        // 新增属性
                        offerInstAttr = toOfferInstAttr(orderRequest, attr, kiteOfferInst, custId);
                        if (Objects.nonNull(offerInstAttr)) {
                            offerInstAttrMap.put(offerInstAttr.getFieldName(), offerInstAttr);
                        }
                    }
                }
            }
        }

        return offerInstAttrMap;
    }

    /**
     * 把KiteAttr转换成OfferInstAttr
     * @param orderRequest
     * @param attr
     * @param kiteOfferInst
     * @param custId
     * @return
     */
    public OfferInstAttr toOfferInstAttr(OrderRequest orderRequest, KiteAttr attr, KiteOfferInst kiteOfferInst,
        String custId) {
        if (!ObjectUtils.allNotNull(orderRequest, attr, kiteOfferInst)) {
            return null;
        }

        Date now = new Date();
        OfferInstAttr offerInstAttr = new OfferInstAttr();
        offerInstAttr.setOfferInstAttrId(IdUtils.generateOfferInstAttrId());
        offerInstAttr.setOwnerCustId(custId);
        offerInstAttr.setActionType(ActionType.A.name());
        offerInstAttr.setOfferInstId(kiteOfferInst.getOfferInstId());
        offerInstAttr.setAttrValue(attr.getValue());
        offerInstAttr.setEffDate(now);
        offerInstAttr.setExpDate(AcceptUtils.getDefaultExpDate());
        offerInstAttr.setLanId(orderRequest.getLanId());
        offerInstAttr.setStatusDate(now);
        offerInstAttr.setCreateDate(now);
        offerInstAttr.setObjId(kiteOfferInst.getOfferInstId());
        offerInstAttr.setObjType(CoreDataProdInst.PRI_C_0011_120100);
        offerInstAttr.setApplyRegionId(orderRequest.getRegionId());
        offerInstAttr.setCreateStaff(orderRequest.getStaffId());
        offerInstAttr.setUpdateStaff(orderRequest.getStaffId());
        offerInstAttr.setUpdateDate(now);
        offerInstAttr.setBusiModEffDate(now);
        offerInstAttr.setCompInstId(kiteOfferInst.getCompInstId());
        offerInstAttr.setFieldName(attr.getFieldName());
        offerInstAttr.setStatusCd(CoreDataOffer.OFF_0003_1200);

        return offerInstAttr;
    }

    /**
     * 根据销售品实例id查询销售品实例属性
     * @param offerInstId
     * @param custId
     * @return
     */
    public static Map<String, OfferInstAttr> getOfferInstAttrMap(String offerInstId, String custId) {
        if (StringUtils.isAnyBlank(offerInstId, custId)) {
            return new HashMap<>();
        }

        Example example = new Example(OfferInstAttr.class);
        example.createCriteria().andEqualTo("offerInstId", offerInstId).andEqualTo("ownerCustId", custId);
        OfferInstAttrMapper mapper = SpringUtil.getBean(OfferInstAttrMapper.class);
        List<OfferInstAttr> offerInstAttrs = mapper.selectByExample(example);

        Map<String, OfferInstAttr> offerInstAttrMap = new HashMap<>();
        for (OfferInstAttr offerInstAttr : offerInstAttrs) {
            if (Objects.equals(ActionType.A.name(), offerInstAttr.getActionType())) {
                offerInstAttr.setNewActionType(ActionType.K.name());
            }
            offerInstAttrMap.put(offerInstAttr.getFieldName(), offerInstAttr);
        }

        return offerInstAttrMap;
    }
}
